from pydantic import BaseModel, Field
from typing import List, Optional, Dict, Any, Union
import datetime

# --- Generic Responses ---
class SuccessResponse(BaseModel):
    success: bool = True
    message: Optional[str] = "操作成功"
    timestamp: int = Field(default_factory=lambda: int(datetime.datetime.now().timestamp() * 1000))

class ErrorDetail(BaseModel):
    code: str
    message: str
    details: Optional[Dict[str, Any]] = None

class ErrorResponse(BaseModel):
    success: bool = False
    error: ErrorDetail
    timestamp: int = Field(default_factory=lambda: int(datetime.datetime.now().timestamp() * 1000))


# --- 0. Server Management ---
class ServerBase(BaseModel):
    servername: str
    ip: str
    port: int = 22
    user: str
    authMethod: int = 0 # 0: password, 1: key
    # password: Optional[str] = None
    # authKey: Optional[str] = None
    description: Optional[str] = None

class ServerCreate(ServerBase):
    password: Optional[str] = None
    authKey: Optional[str] = None

class ServerInfo(ServerBase):
    id: str

    class Config:
        from_attributes = True

class ServerAddResponseData(BaseModel):
    id: str
    status: str

class ServerAddResponse(SuccessResponse):
    data: ServerAddResponseData

class ActivateServerResponseData(BaseModel):
    currentServerId: str

class ActivateServerResponse(SuccessResponse):
    data: ActivateServerResponseData


# --- 1. System Info ---
class SystemInfoData(BaseModel):
    os: str
    hostname: str
    uptime: str
    architecture: str
    # kernel: str
    # distribution: str

class SystemInfoResponse(SuccessResponse):
    data: SystemInfoData

class CPUOverview(BaseModel):
    cores: int
    usage: float
    load1m: float
    load5m: float
    load15m: float

class MemoryOverview(BaseModel):
    total: int
    used: int
    usage: float
    oomKills: int

class DiskOverview(BaseModel):
    totalSpace: int
    totalIOPS: float
    totalThroughput: float

class NetworkOverview(BaseModel):
    interfaces: int
    totalRxThroughput: float
    totalTxThroughput: float

class SystemOverviewData(BaseModel):
    cpu: CPUOverview
    memory: MemoryOverview
    disk: DiskOverview
    network: NetworkOverview

class SystemOverviewResponse(SuccessResponse):
    data: SystemOverviewData

class MysqlRealtimeData(BaseModel):
    qps: float
    tps: float
    slowQueries: int
    threadsConnected: int
    threadsRunning: int
    abortedConnects: int
    innodbBufferPoolReads: int
    innodbBufferPoolReadRequests: int
    innodbRowLocksWaits: int
    innodbRowLockTime: int
    innodbLogWaits: int

class MysqlRealtimeResponse(SuccessResponse):
    data: MysqlRealtimeData

# --- 2. CPU Monitoring ---
class PerCoreUsage(BaseModel):
    core: int
    user: float
    system: float
    iowait: float
    idle: float

class CPURealtimeData(BaseModel):
    cores: int
    usage: float
    load1m: float
    load5m: float
    load15m: float
    processCount: int
    contextSwitchesPerSec: int
    interruptsPerSec: int
    syscallsPerSec: int
    perCoreUsage: List[PerCoreUsage]

class CPURealtimeResponse(SuccessResponse):
    data: CPURealtimeData

class ProcessInfo(BaseModel):
    pid: int
    ppid: int
    user: str
    cpu: float
    mem: float
    vsz: int
    rss: int
    stat: str
    start: str
    time: str
    command: str

class ProcessListResponse(SuccessResponse):
    data: List[ProcessInfo]


# --- 3. Memory Monitoring ---
class SwapInfo(BaseModel):
    total: int
    used: int
    usage: float

class VmstatInfo(BaseModel):
    swappiness: int
    vfsCachePressure: int
    dirtyRatio: int
    dirtyBackgroundRatio: int
    transparentHugepage: str
    pageScanRate: int
    pgscanKswapd: int
    pgscanDirect: int

class MemoryRealtimeData(BaseModel):
    total: int
    used: int
    free: int
    available: int
    buffers: int
    usage: float
    swap: SwapInfo
    oomKills: int
    vmstat: VmstatInfo

class MemoryRealtimeResponse(SuccessResponse):
    data: MemoryRealtimeData


# --- 4. Disk Monitoring ---
class DiskDeviceRealtime(BaseModel):
    name: str
    size: int
    used: int
    usage: float
    readIOPS: float
    writeIOPS: float
    readThroughput: float
    writeThroughput: float
    await_: float = Field(..., alias="await")
    util: float
    scheduler: str
    queueDepth: int
    readAhead: int

class FilesystemRealtime(BaseModel):
    mountPoint: str
    device: str
    type: str
    size: int
    used: int
    available: int
    usage: float
    inodes: int
    inodesUsed: int
    inodesAvailable: int
    inodeUsage: float

class DiskRealtimeData(BaseModel):
    devices: List[DiskDeviceRealtime]
    filesystems: List[FilesystemRealtime]

class DiskRealtimeResponse(SuccessResponse):
    data: DiskRealtimeData


# --- 5. Network Monitoring ---
class NetworkInterfaceRealtime(BaseModel):
    name: str
    rxPacketsPerSec: float
    txPacketsPerSec: float
    rxBytesPerSec: float
    txBytesPerSec: float
    rxDroppedPerSec: int
    txDroppedPerSec: int
    rxErrorsPerSec: int
    txErrorsPerSec: int
    speed: str
    duplex: str
    mtu: int

class TCPInfo(BaseModel):
    listenOverflows: int
    syncookiesSent: int
    listenDrops: int
    retransSegs: int
    congestionControl: str
    windowScaling: bool
    maxSynBacklog: int
    somaxconn: int
    tcpRmem: List[int]
    tcpWmem: List[int]

class NetworkRealtimeData(BaseModel):
    interfaces: List[NetworkInterfaceRealtime]
    tcp: TCPInfo

class NetworkRealtimeResponse(SuccessResponse):
    data: NetworkRealtimeData

# --- historical metrics ---
class CPUHistoryData(BaseModel):
    timestamps: List[int]
    datas: List[CPURealtimeData]

class CPUHistoryResponse(SuccessResponse):
    data: CPUHistoryData

class MemoryHistoryData(BaseModel):
    timestamps: List[int]
    datas: List[MemoryRealtimeData]

class MemoryHistoryResponse(SuccessResponse):
    data: MemoryHistoryData

class DiskHistoryData(BaseModel):
    timestamps: List[int]
    datas: List[DiskRealtimeData]

class DiskHistoryResponse(SuccessResponse):
    data: DiskHistoryData

class NetworkHistoryData(BaseModel):
    timestamps: List[int]
    datas: List[NetworkRealtimeData]

class NetworkHistoryResponse(SuccessResponse):
    data: NetworkHistoryData

class MysqlHistoryData(BaseModel):
    timestamps: List[int]
    datas: List[MysqlRealtimeData]

class MysqlHistoryResponse(SuccessResponse):
    data: MysqlHistoryData

# --- 6. Config Management ---
class ConfigUpdateRequest(BaseModel):
    # Using dict to be flexible for any category
    config: Dict[str, Any]

class ConfigUpdateResponseData(BaseModel):
    updated: bool
    changedParameters: List[str]

class ConfigUpdateResponse(SuccessResponse):
    data: ConfigUpdateResponseData


# --- 7. Optimization ---
class OptimizationSuggestion(BaseModel):
    type: str
    report: str
    param: List[str]

class SuggestionData(BaseModel):
    appid: str | None
    content: List[OptimizationSuggestion]
    bottleneck: str
    suggestionId: str

class SuggHistoryData(SuggestionData):
    improvement: float

class SuggestionResponse(SuccessResponse):
    data: SuggestionData

class SuggestionApplyRequest(BaseModel):
    suggestionId: str

class SuggestionApplyData(BaseModel):
    improvement: float
    health: int
    before: float
    after: float

class SuggestionApplyResponse(SuccessResponse):
    data: SuggestionApplyData

class SuggestionHistoryData(BaseModel):
    timestamps: List[int]
    datas: List[SuggHistoryData]

class SuggestionHistoryResponse(SuccessResponse):
    data: SuggestionHistoryData

class ParameterChange(BaseModel):
    name: str
    value: Any

# --- 8. App Management ---
class AppRunningResponse(SuccessResponse):
    data: List[str]

class AppCreate(BaseModel):
    serverId: str
    appType: str
    name: Optional[str] = None
    description: Optional[str] = None
    config: Dict[str, Any]

class AppRetrieve(BaseModel):
    appid: str
    appType: str
    name: Optional[str] = None
    description: Optional[str] = None
    # config: Dict[str, Any]

class AppCreateResponse(SuccessResponse):
    data: AppRetrieve

class AppListResponse(SuccessResponse):
    data: List[AppRetrieve]

class AppAnalyzeRequest(BaseModel):
    appid: str

class AppAnalyzeApplyRequest(SuggestionApplyRequest, AppAnalyzeRequest):
    pass